package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.ConfigConstant;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.StageTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.PaasFormHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.SummaryDataPoJo;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataGetDTO;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.ParseSingleRowDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.UserAndDepartmentGetDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.pojo.vo.ParseSingleRowDataVO;
import com.xbongbong.paas.service.dynamic.crm.strategy.DynamicStrategyFactory;
import com.xbongbong.paas.service.log.crm.operation.CompetitorOperationLogHandle;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.explain.FormDataDetailFormExplainHandleName;
import com.xbongbong.parent.interfaces.logger.OperationLogFactory;
import com.xbongbong.parent.interfaces.logger.OperationLogHandle;
import com.xbongbong.parent.parse.data.FormDataGetAnalysisDataHelp;
import com.xbongbong.pro.competitor.pojo.QueryLinkedOpportunityPojo;
import com.xbongbong.pro.competitor.pojo.dto.CompetitorDeleteBatchDTO;
import com.xbongbong.pro.competitor.pojo.dto.CompetitorDeleteBatchVO;
import com.xbongbong.pro.competitor.pojo.dto.CompetitorEditAttrUpdateDTO;
import com.xbongbong.pro.competitor.pojo.dto.CompetitorPanoramaGetDTO;
import com.xbongbong.pro.competitor.pojo.dto.CompetitorUpdateBatchDTO;
import com.xbongbong.pro.competitor.pojo.dto.CompetitorUpdateDTO;
import com.xbongbong.pro.competitor.pojo.dto.CompetitorUserAndDeptGetDTO;
import com.xbongbong.pro.competitor.pojo.dto.LinkedOpportunityListDTO;
import com.xbongbong.pro.competitor.pojo.dto.log.CompetitorPortionVisibleLogDTO;
import com.xbongbong.pro.competitor.pojo.vo.CompetitorPanoramaDataVO;
import com.xbongbong.pro.competitor.pojo.vo.CompetitorPanoramaGetVO;
import com.xbongbong.pro.competitor.pojo.vo.CompetitorUpdateBatchVO;
import com.xbongbong.pro.competitor.pojo.vo.CompetitorUserAndDeptGetVO;
import com.xbongbong.pro.competitor.pojo.vo.LinkedOpportunityListVO;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.domain.entity.DetailTabConfigEntity;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.OpportunityErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.enums.permission.enums.UpdateProPermissionAliasEnum;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.formexplain.pojo.vo.HandlerExplainVO;
import com.xbongbong.pro.listbatch.pojo.dto.AddLabelDTO;
import com.xbongbong.pro.listbatch.pojo.dto.PortionDepDTO;
import com.xbongbong.pro.listbatch.pojo.dto.PortionUserDTO;
import com.xbongbong.pro.listbatch.pojo.vo.TeamBatchVO;
import com.xbongbong.pro.log.pojo.dto.UpdateBatchOperationLogDTO;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.userteam.pojo.UserTeamPermissonPojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.SaleStageEntity;
import com.xbongbong.saas.domain.entity.competitor.CompetitorAnalysisEntity;
import com.xbongbong.saas.domain.entity.competitor.CompetitorEntity;
import com.xbongbong.saas.domain.entity.competitor.CompetitorUserEntity;
import com.xbongbong.saas.domain.entity.competitor.LinkedOpportunityItemEntity;
import com.xbongbong.saas.domain.entity.ext.OpportunityEntityExt;
import com.xbongbong.saas.enums.CompetitorErrorCodeEnum;
import com.xbongbong.saas.enums.CompetitorPanoramaEnum;
import com.xbongbong.saas.enums.DetailTabEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.CompetitorEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.help.BasicHelper;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.model.CompetitorAnalysisModel;
import com.xbongbong.saas.model.CompetitorModel;
import com.xbongbong.saas.model.CompetitorUserModel;
import com.xbongbong.saas.model.DetailTabConfigModel;
import com.xbongbong.saas.model.OpportunityModel;
import com.xbongbong.saas.model.SaleStageModel;
import com.xbongbong.saas.service.CompetitorService;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.service.toolbox.help.UserTeamHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.enums.DataPermissionEnum;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.join.query.HasChildQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author: yingjf
 * @date: 2022/8/11 11:13
 * @description: 竞争对手业务实现类
 */
@Slf4j
@Service("competitorService")
public class CompetitorServiceImpl implements CompetitorService{

    private static final Logger LOG = LoggerFactory.getLogger(CompetitorServiceImpl.class);

    @Resource
    private CompetitorModel competitorModel;
    @Resource
    private CompetitorUserModel competitorUserModel;
    @Resource
    private LogHelp logHelp;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private CompetitorAnalysisModel competitorAnalysisModel;
    @Resource
    private SaleStageModel saleStageModel;
    @Resource
    private EsHelper esHelper;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private UserModel userModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private PaasFormHelp paasFormHelp;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private FormDataGetAnalysisDataHelp formDataGetAnalysisDataHelp;
    @Resource
    private UserTeamHelp userTeamHelp;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private FormDataDetailFormExplainHandleName formDataDetailFormExplainHandleName;
    @Resource
    private ImportHelper importHelper;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private DynamicStrategyFactory dynamicStrategyFactory;
    @Resource
    private OpportunityModel opportunityModel;
    @Resource
    private OperationLogFactory operationLogFactory;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private DetailTabConfigModel detailTabConfigModel;

    @Override
    public void batchEditAttr(CompetitorEditAttrUpdateDTO competitorEditAttrUpdateDTO) throws XbbException {
        try {
            //条件封装
            List<Long> dataIdList = competitorEditAttrUpdateDTO.getDataIdList();
            String corpid = competitorEditAttrUpdateDTO.getCorpid();
            Object value = competitorEditAttrUpdateDTO.getValue();
            Map<String, Object> params = new HashMap<>();
            params.put("corpid",corpid);
            params.put("idIn",dataIdList);
            params.put("del",DelEnum.NORMAL.getDel());
            //数据查询
            List<CompetitorEntity> competitorEntityList = competitorModel.findEntitys(params);
            if (Objects.isNull(competitorEntityList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            //封装更新对象
            List<CompetitorUpdateDTO> competitorUpdateDTOList = dataIdList.stream().map(id -> {
                CompetitorUpdateDTO competitorUpdateDTO = new CompetitorUpdateDTO();
                competitorUpdateDTO.setId(id);
                JSONObject data = ProSaveHelp.getBatchUpdateData(competitorEditAttrUpdateDTO.getFieldEditedList());
                competitorUpdateDTO.setData(data);
                return competitorUpdateDTO;
            }).collect(Collectors.toList());

            //封装批量修改对象
            if (CollectionUtils.isNotEmpty(competitorUpdateDTOList)) {
                CompetitorUpdateBatchDTO competitorUpdateBatchDTO = new CompetitorUpdateBatchDTO();
                BeanUtil.copyProperties(competitorEditAttrUpdateDTO,competitorUpdateBatchDTO);
                competitorUpdateBatchDTO.setCompetitorUpdateDTOList(competitorUpdateDTOList);
                //执行批量修改操作
                updateBatch(competitorUpdateBatchDTO);
            }

            //日志记录批量操作
            try {
                List<CompetitorEntity> newCompetitorList = competitorModel.findEntitys(params);
                List<PaasFormDataEntity> newDataList = new ArrayList<>();
                List<PaasFormDataEntity> oldDataList = new ArrayList<>();
                BeanUtil.copyPropertiesList(competitorEntityList,oldDataList,PaasFormDataEntity.class);
                BeanUtil.copyPropertiesList(newCompetitorList,newDataList,PaasFormDataEntity.class);
                String userId = competitorEditAttrUpdateDTO.getUserId();
                String userName = competitorEditAttrUpdateDTO.getLoginUserName();
                Long formId = competitorEditAttrUpdateDTO.getFormId();
                Integer businessType = competitorEditAttrUpdateDTO.getBusinessType();

                OperationLogHandle operationLogHandle = operationLogFactory.getOperationLogHandle(competitorEditAttrUpdateDTO.getSaasMark(),competitorEditAttrUpdateDTO.getBusinessType());
                UpdateBatchOperationLogDTO updateBatchOperationLogDTO = new UpdateBatchOperationLogDTO( corpid, userId, userName, dataIdList.size(), competitorEditAttrUpdateDTO.getHttpHeader(), competitorEditAttrUpdateDTO.getLogFieldEditedList(),
                        newDataList, oldDataList, formId, businessType,1);;
                operationLogHandle.updateBatch(updateBatchOperationLogDTO);
            }catch (Exception e){
                log.error("竞争对手批量修改日志保存失败，失败原因：",e);
            }

        }catch (XbbException e) {
            LOG.error("CompetitorServiceImpl.batchEditAttr 报错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }catch (Exception e) {
            LOG.error("CompetitorServiceImpl.batchEditAttr 报错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public CompetitorUpdateBatchVO updateBatch(CompetitorUpdateBatchDTO competitorUpdateBatchDTO) throws XbbException {
        CompetitorUpdateBatchVO competitorUpdateBatchVO = new CompetitorUpdateBatchVO();
        try {
            String corpid = competitorUpdateBatchDTO.getCorpid();
            List<CompetitorUpdateDTO> competitorUpdateDTOList = competitorUpdateBatchDTO.getCompetitorUpdateDTOList();

            //根据字段解释封装更新对象
            List<UpdateDataEntity> updateDataEntityList = competitorUpdateDTOList.stream()
                    .map(competitor -> ExplainUtil.getUpdateData(competitor.getId(), competitor.getData(), corpid))
                    .collect(Collectors.toList());

            if (CollectionsUtil.isNotEmpty(updateDataEntityList)){
                competitorModel.updateBatch(updateDataEntityList,corpid);
            }
        }catch (Exception e){
            LOG.error("CompetitorServiceImpl.updateBatch 批量修改竞争对手失败，失败原因：",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001,SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return competitorUpdateBatchVO;
    }

    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        try {
            JSONObject data = validateDataDTO.getData();
            JSONArray deptArray = data.getJSONArray(CompetitorEnum.VISBLE_DEPT.getAttr());
            if (Objects.nonNull(deptArray)) {
                List<Object> deptList = deptArray.toJavaList(Object.class);
                validateDataDTO.setVisbleDept(deptList);
            }
            JSONArray userArray = data.getJSONArray(CompetitorEnum.VISBLE_USER.getAttr());
            if (Objects.nonNull(userArray)) {
                List<Object> userList = userArray.toJavaList(Object.class);
                validateDataDTO.setVisbleUser(userList);
            }
            data.remove(CompetitorEnum.VISBLE_DEPT.getAttr());
            data.remove(CompetitorEnum.VISBLE_USER.getAttr());
            validateDataDTO.setData(data);
        } catch (Exception e) {
            log.error("CompetitorServiceImpl.beforeSave error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public void afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        if (newPaasFormDataEntity != null) {
            // 保存竞争对手可见部门和可见人
            List<Object> visbleDept = saasFormSaveDTO.getVisbleDept();
            List<Object> visbleUser = saasFormSaveDTO.getVisbleUser();

            competitorUserModel.refreshProductUser(saasFormSaveDTO, newPaasFormDataEntity.getId(), newPaasFormDataEntity.getCorpid(),visbleDept,visbleUser);
        }
    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        if (newPaasFormDataEntity != null) {
            // 保存负责人
            List<Object> visbleDept = saasFormSaveDTO.getVisbleDept();
            List<Object> visbleUser = saasFormSaveDTO.getVisbleUser();

            competitorUserModel.refreshProductUser(saasFormSaveDTO, newPaasFormDataEntity.getId(), newPaasFormDataEntity.getCorpid(),visbleDept,visbleUser);
        }
    }

    @Override
    public void afterSaveForUpdateWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        if (newPaasFormDataEntity != null) {
            // 保存负责人
            List<Object> visbleDept = saasFormSaveDTO.getVisbleDept();
            List<Object> visbleUser = saasFormSaveDTO.getVisbleUser();

            competitorUserModel.refreshProductUser(saasFormSaveDTO, newPaasFormDataEntity.getId(), newPaasFormDataEntity.getCorpid(),visbleDept,visbleUser);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CompetitorDeleteBatchVO deleteBatch(CompetitorDeleteBatchDTO competitorDeleteBatchDTO) throws XbbException {
        CompetitorDeleteBatchVO competitorDeleteBatchVO = new CompetitorDeleteBatchVO();
        try {
            List<Long> dataIdList = competitorDeleteBatchDTO.getDataIdList();
            String corpid = competitorDeleteBatchDTO.getCorpid();
            //查询竞争对手列表数据
            Map<String, Object> params = BeanUtil.convertBean2Map(competitorDeleteBatchDTO);
            params.put("idIn",dataIdList);
            List<CompetitorEntity> competitorList = competitorModel.findEntitys(params);
            if (Objects.isNull(competitorList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }

            List<Long> deleteIdList = competitorList.stream().map(competitor -> competitor.getId()).collect(Collectors.toList());

            //批量删除竞争对手
            if (!dataIdList.isEmpty()){
                competitorModel.deleteBatch(deleteIdList, corpid);
                // 找到机会
                params.clear();
                params.put("corpid",corpid);
                params.put("competitorIdIn",deleteIdList);
                params.put("pageSize",50);
                params.put("del",0);
                List<CompetitorAnalysisEntity> competitorAnalysisEntityList = competitorAnalysisModel.findEntitys(params);
                Set<Long> opportunityIdSet = new HashSet<>();
                competitorAnalysisEntityList.forEach(item->{
                    opportunityIdSet.add(item.getOppotunityId());
                });

                List<OpportunityEntityExt> opportunityEntityExtList = opportunityModel.getByKeysWithoutSub(opportunityIdSet, corpid);
                List<UpdateDataEntity> updateDataEntityList = new ArrayList<>();
                opportunityEntityExtList.forEach(item->{
                    JSONObject updateJsonObject = new JSONObject();
                    JSONObject data = item.getData();
                    try {
                        List<Long> linkCompetitorIds = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, SalesOpportunityEnum.LINK_COMPETITOR.getAttr(), new JSONArray()).toJavaList(Long.class);
                        List<String> linkCompetitorNames = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, SalesOpportunityEnum.LINK_COMPETITOR_LINK_TEXT.getAttr(), new JSONArray()).toJavaList(String.class);
                        Long winCompetitorId = FastJsonHelper.getLongFromFormData(data, SalesOpportunityEnum.WIN_COMPETITOR.getAttr());

                        List<Long> newlinkCompetitorIds = new ArrayList<>();
                        List<String> newlinkCompetitorNames = new ArrayList<>();
                        for(int i=0;i<linkCompetitorIds.size();i++){
                            Long linkCompetitorId = linkCompetitorIds.get(i);
                            String linkCompetitorName = linkCompetitorNames.get(i);
                            if(!deleteIdList.contains(linkCompetitorId)){
                                newlinkCompetitorIds.add(linkCompetitorId);
                                newlinkCompetitorNames.add(linkCompetitorName);
                            }
                        }
                        if(deleteIdList.contains(winCompetitorId)){
                            updateJsonObject.put(SalesOpportunityEnum.WIN_COMPETITOR.getAttr(), null);
                            updateJsonObject.put(SalesOpportunityEnum.WIN_COMPETITOR_LINK_TEXT.getAttr(), null);
                        }
                        updateJsonObject.put(SalesOpportunityEnum.LINK_COMPETITOR.getAttr(), newlinkCompetitorIds);
                        updateJsonObject.put(SalesOpportunityEnum.LINK_COMPETITOR_LINK_TEXT.getAttr(), newlinkCompetitorNames);
                        UpdateDataEntity updateData = ExplainUtil.getUpdateData(item.getDataId(), updateJsonObject, corpid);
                        updateDataEntityList.add(updateData);
                    } catch (XbbException e) {
                        log.error("com.xbongbong.saas.service.impl.CompetitorServiceImpl.deleteBatch 删除竞争对手更新机会失败",e);
                    }
                });
                if(CollectionsUtil.isNotEmpty(updateDataEntityList)){
                    opportunityModel.updateBatch(updateDataEntityList,corpid);
                }
                // 删除竞争对手需要删除竞争对手关系
                competitorAnalysisModel.deleteByCompetitorIds(deleteIdList,corpid);
            }

            //记录批量删除日志
            recordBatchDeleteLog(competitorList,competitorDeleteBatchDTO);
            //返回批量删除竞争对手id
            List<Long> returnDeleteIdList = competitorList.stream().map(item -> item.getId()).collect(Collectors.toList());
            competitorDeleteBatchVO.setDeleteIds(returnDeleteIdList);
        } catch (Exception e){
            LOG.error("CompetitorServiceImpl.deleteBatch 批量删除竞争对手报错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return competitorDeleteBatchVO;
    }


    @Override
    public CompetitorPanoramaGetVO panoramaGet(CompetitorPanoramaGetDTO competitorPanoramaGetDTO) throws XbbException {
        CompetitorPanoramaGetVO competitorPanoramaGetVO = new CompetitorPanoramaGetVO();
        try {
            String corpid = competitorPanoramaGetDTO.getCorpid();
            PaasMenuEntity salesOpportunityMenu = paasMenuModel.getByAlias(XbbRefTypeEnum.SALES_OPPORTUNITY.getAlias(), corpid);
            String salesOpportunityMenuName = salesOpportunityMenu.getName();
            Long dataId = competitorPanoramaGetDTO.getDataId();
            String userId = competitorPanoramaGetDTO.getUserId();
            UserVO loginUser = competitorPanoramaGetDTO.getLoginUser();
            if (!isOpenSaleOpportunityTab(competitorPanoramaGetDTO)){
                competitorPanoramaGetVO.setPanoramaList(packageEmptyPanoramaList(salesOpportunityMenuName));
                return competitorPanoramaGetVO;
            }
            if(loginUser!=null&&!loginUser.getPermSet().contains(ProPermissionAliasEnum.OPPORTUNITY_VIEW.getAlias())){
                competitorPanoramaGetVO.setPanoramaList(packageEmptyPanoramaList(salesOpportunityMenuName));
                return competitorPanoramaGetVO;
            }
//            UserEntity userEntity = new UserEntity();
//            BeanUtil.copyProperties(loginUser, userEntity);
//            boolean isBoos = userModel.isBoss(userEntity);

            Map<String,Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(StringConstant.CORPID,corpid);
            params.put("competitorId",dataId);
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            Integer count = competitorAnalysisModel.getEntitysCount(params);

            Long opportunityCount = 0L;
            Double opportunityMoney = 0.0;
            Long winOpportunityCount = 0L;
            Double winOpportunityMoney = 0.0;
            Long loseOpportunityCount = 0L;
            Double loseOpportunityMoney = 0.0;

            int pageSize = 100;
            int totalPage = (count%pageSize)==0?0:(count/pageSize)+1;
            int nowPage = 1;

            List<PaasFormEntityExt> enableFormList = paasFormModel.getEnableFormList(corpid, XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
            Set<Long> enableFormIdSet = new HashSet<>();
            enableFormList.forEach(item->{
                enableFormIdSet.add(item.getId());
            });

            while(nowPage<=totalPage){
                params.clear();
                params.put(StringConstant.CORPID,corpid);
                params.put("competitorId",dataId);
                params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                List<CompetitorAnalysisEntity> competitorAnalysisModelEntitys = competitorAnalysisModel.findEntitys(params);
                Set<Long> opportunityIdSet = new HashSet<>();
                competitorAnalysisModelEntitys.forEach(item->{
                    opportunityIdSet.add(item.getOppotunityId());
                });

                List<PaasFormDataEntityExt> opportunityEntityExtList = getOpportunity(corpid,userId, opportunityIdSet,enableFormIdSet,loginUser );
                Set<Long> stageIdSet = new HashSet<>();
                opportunityEntityExtList.forEach(item->{
                    stageIdSet.add(item.getData().getLong(SalesOpportunityEnum.STAGE_ID.getAttr()));
                });
                params.clear();
                params.put(StringConstant.CORPID,corpid);
                params.put("idIn",stageIdSet);
                params.put("typeIn", Arrays.asList(StageTypeEnum.SUCCESS_STAGE.getType(),StageTypeEnum.FAIL_STAGE.getType()));
                params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                List<SaleStageEntity> saleStageEntityList = saleStageModel.findEntitys(params);
                Set<Long> successSaleStageIdSet = new HashSet<>();
                Set<Long> failSaleStageIdSet = new HashSet<>();
                saleStageEntityList.forEach(item->{
                    Integer type = item.getType();
                    if(Objects.equals(type,StageTypeEnum.SUCCESS_STAGE.getType())){
                        successSaleStageIdSet.add(item.getId());
                    }else if(Objects.equals(type,StageTypeEnum.FAIL_STAGE.getType())){
                        failSaleStageIdSet.add(item.getId());
                    }
                });
                for(int i =0; i<opportunityEntityExtList.size(); i++){
                    PaasFormDataEntityExt item = opportunityEntityExtList.get(i);
                    Long id = item.getId();
                    JSONObject data = item.getData();
                    Long stageId = data.getLong(SalesOpportunityEnum.STAGE_ID.getAttr());
                    Double estimateAmount = data.getDouble(SalesOpportunityEnum.ESTIMATE_AMOUNT.getAttr());
                    if(estimateAmount==null){
                        estimateAmount = 0.0;
                    }
                    opportunityCount++;
                    opportunityMoney+=estimateAmount;
                    if(successSaleStageIdSet.contains(stageId)){
                        // 成功阶段的机会
                        winOpportunityMoney+=estimateAmount;
                        winOpportunityCount++;
                    }
                    // 非成功阶段
                    Long competitorId = data.getLong(SalesOpportunityEnum.WIN_COMPETITOR.getAttr());
                    if(competitorId==dataId /*&& failSaleStageIdSet.contains(stageId)*/){
                        loseOpportunityMoney+=estimateAmount;
                        loseOpportunityCount++;
                    }

                }
                nowPage++;
            }
            List<List<CompetitorPanoramaDataVO>> packagePanoramaList = packagePanoramaList(true,salesOpportunityMenuName,opportunityCount, opportunityMoney, winOpportunityCount, winOpportunityMoney, loseOpportunityCount, loseOpportunityMoney);
            competitorPanoramaGetVO.setPanoramaList(packagePanoramaList);
        }catch (XbbException e){
            throw e;
        }catch (Exception e){
            log.error("com.xbongbong.saas.service.impl.CompetitorServiceImpl.panoramaGet",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return competitorPanoramaGetVO;
    }

    @Override
    public CompetitorUserAndDeptGetVO userAndDeptGet(CompetitorUserAndDeptGetDTO competitorUserAndDeptGetDTO) throws XbbException {
        Long dataId = competitorUserAndDeptGetDTO.getDataId();
        String corpid = competitorUserAndDeptGetDTO.getCorpid();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put("dataId", dataId);
        param.put("del", 0);
        List<CompetitorUserEntity> competitorUserList = competitorUserModel.findEntitys(param);
        competitorUserList = competitorUserList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(
                () -> new TreeSet<>(Comparator.comparing(o -> o.getRelationId() + "#" + o.getType()))),
                ArrayList::new));
        for (CompetitorUserEntity competitorUser : competitorUserList) {
            if (Objects.equals(competitorUser.getType(), 1)) {
                Long depId = StringUtil.StringToLong(competitorUser.getRelationId());
                if (Objects.equals(depId, 0L)) {
                    depId = 1L;
                }
                DepartmentEntity department = departmentModel.getByKey(depId, corpid);
                if (department != null) {
                    competitorUser.setUserName(department.getName());
                }
            } else {
                UserEntity user = userModel.getByKey(competitorUser.getRelationId(), corpid);
                if (user == null) {
                    competitorUser.setUserName("");
                    competitorUser.setUserAvatar(ConfigConstant.DEFAULT_PIC);
                } else {
                    competitorUser.setUserName(user.getName());
                    competitorUser.setUserAvatar(StringUtil.isEmpty(user.getAvatar()) ? ConfigConstant.DEFAULT_PIC : user.getAvatar());
                }
            }
        }
        CompetitorUserAndDeptGetVO UserAndDeptGetVO = new CompetitorUserAndDeptGetVO();
        UserAndDeptGetVO.setManagerList(competitorUserList);
        UserTeamPermissonPojo userTeamPermissonPojo = new UserTeamPermissonPojo();
        userTeamPermissonPojo.setHaveEditProductPermission(false);
        UserVO userVO = competitorUserAndDeptGetDTO.getLoginUser();
        UpdateProPermissionAliasEnum updateProPermissionAliasEnum = UpdateProPermissionAliasEnum.getByCode(XbbRefTypeEnum.COMPETITOR.getCode());
        if (Objects.nonNull(updateProPermissionAliasEnum)) {
            if (userVO!=null && userVO.getPermSet().contains(updateProPermissionAliasEnum.getAlias())) {
                userTeamPermissonPojo.setHaveEditProductPermission(true);
                UserAndDeptGetVO.setUserTeamPermissonPojo(userTeamPermissonPojo);
            }
        }
        UserAndDeptGetVO.setUserTeamPermissonPojo(userTeamPermissonPojo);
        return UserAndDeptGetVO;
    }

    @Override
    public BaseVO portionDep(PortionDepDTO portionDepDTO) throws XbbException {
        if (portionDepDTO.getDataIdList().size() > StringConstant.MAX_SIZE) {
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200029);
        }
        TeamBatchVO teamBatchVO = new TeamBatchVO();
        List<Long> idList = portionDepDTO.getDataIdList();
        String corpid = portionDepDTO.getCorpid();
        Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid",corpid);
        map.put("dataIdIn",idList);
        map.put("type",1);
        map.put("del",0);
        List<CompetitorUserEntity> competitorUserEntityList = competitorUserModel.findEntitys(map);
        List<Long> depIdList = portionDepDTO.getDepIdList();
        Map<Long,List<String>> hasUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (CompetitorUserEntity entity : competitorUserEntityList){
            List<String> depList = hasUserMap.getOrDefault(entity.getDataId(),new ArrayList<>());
            depList.add(entity.getRelationId());
            hasUserMap.put(entity.getDataId(),depList);
        }
        List<CompetitorUserEntity> insetBatchList = new ArrayList<>();
        for (Long id : idList){
            for (Long depId : depIdList){
                if (hasUserMap.getOrDefault(id,new ArrayList<>()).contains(depId.toString())){
                    continue;
                }
                CompetitorUserEntity competitorUserEntity = new CompetitorUserEntity();
                competitorUserEntity.setCorpid(corpid);
                competitorUserEntity.setDataId(id);
                competitorUserEntity.setType(1);
                competitorUserEntity.setRelationId(depId.toString());
                insetBatchList.add(competitorUserEntity);
            }
        }
        //批量插入
        if (!insetBatchList.isEmpty()) {
            competitorUserModel.inserBatch(insetBatchList);
        }
        //日志记录
         afterPortionDep(portionDepDTO);
        return teamBatchVO;
    }

    /**
     * tab页分配可见部门日志记录
     * @param portionDepDTO
     */
    private void afterPortionDep(PortionDepDTO portionDepDTO){
        CompetitorPortionVisibleLogDTO logDTO = new CompetitorPortionVisibleLogDTO();
        BeanUtil.copyProperties(portionDepDTO,logDTO);
        logDTO.setDataIdList(portionDepDTO.getDataIdList());
        List<Long> depIdList = portionDepDTO.getDepIdList();

        if (CollectionsUtil.isNotEmpty(depIdList)){
            List<String> depIdStrList = depIdList.stream().map(item -> item.toString()).collect(Collectors.toList());
            logDTO.setRelationIdList(depIdStrList);
        }
        CompetitorOperationLogHandle logHandler = (CompetitorOperationLogHandle) operationLogFactory.getOperationLogHandle(SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.COMPETITOR.getCode());
        if (Objects.nonNull(logHandler)) {
            logHandler.portionCompetitorDep(logDTO);
        }
    }

    @Override
    public BaseVO portionUser(PortionUserDTO portionUserDTO) throws XbbException {
        if (portionUserDTO.getDataIdList().size() > StringConstant.MAX_SIZE) {
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200029);
        }
        TeamBatchVO teamBatchVO = new TeamBatchVO();
        List<Long> idList = portionUserDTO.getDataIdList();
        String corpid = portionUserDTO.getCorpid();
        Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid",portionUserDTO.getCorpid());
        map.put("dataIdIn",idList);
        map.put("type",0);
        map.put("del",0);
        List<CompetitorUserEntity> competitorUserEntityList = competitorUserModel.findEntitys(map);
        List<String> userIdList = portionUserDTO.getUserIdList();
        Map<Long,List<String>> hasUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (CompetitorUserEntity entity : competitorUserEntityList){
            List<String> userList = hasUserMap.getOrDefault(entity.getDataId(),new ArrayList<>());
            userList.add(entity.getRelationId());
            hasUserMap.put(entity.getDataId(),userList);
        }
        List<CompetitorUserEntity> insetBatchList = new ArrayList<>();
        for (Long id : idList){
            for (String userId : userIdList){
                if (hasUserMap.getOrDefault(id,new ArrayList<>()).contains(userId)){
                    continue;
                }
                CompetitorUserEntity competitorUserEntity = new CompetitorUserEntity();
                competitorUserEntity.setCorpid(corpid);
                competitorUserEntity.setDataId(id);
                competitorUserEntity.setType(0);
                competitorUserEntity.setRelationId(userId);
                insetBatchList.add(competitorUserEntity);
            }
        }
        //批量插入
        if (!insetBatchList.isEmpty()){
            competitorUserModel.inserBatch(insetBatchList);
        }
        // 日志记录
        afterPortionUser(portionUserDTO);
        return teamBatchVO;
    }

    /**
     * tab页分配可见人日志记录
     * @param portionUserDTO
     */
    private void afterPortionUser(PortionUserDTO portionUserDTO){
        CompetitorPortionVisibleLogDTO logDTO = new CompetitorPortionVisibleLogDTO();
        BeanUtil.copyProperties(portionUserDTO,logDTO);
        logDTO.setDataIdList(portionUserDTO.getDataIdList());
        logDTO.setRelationIdList(portionUserDTO.getUserIdList());
        CompetitorOperationLogHandle logHandler = (CompetitorOperationLogHandle) operationLogFactory.getOperationLogHandle(SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.COMPETITOR.getCode());
        if (Objects.nonNull(logHandler)) {
            logHandler.portionCompetitorUser(logDTO);
        }
    }

    @Override
    public LinkedOpportunityListVO linkedOpportunityList(LinkedOpportunityListDTO linkedOpportunityGetDTO) throws XbbException {
        LinkedOpportunityListVO linkedOpportunityListVO = new LinkedOpportunityListVO();
        try {
            List<LinkedOpportunityItemEntity> linkedOpportunityItemEntityArrayList = new ArrayList<>();
            linkedOpportunityListVO.setList(linkedOpportunityItemEntityArrayList);
            String corpid = linkedOpportunityGetDTO.getCorpid();
            String userId = linkedOpportunityGetDTO.getUserId();
            Long dataId = linkedOpportunityGetDTO.getDataId();
            UserVO loginUser = linkedOpportunityGetDTO.getLoginUser();
            Integer page = linkedOpportunityGetDTO.getPage();
            Integer pageSize = linkedOpportunityGetDTO.getPageSize();
            JSONArray queryTime = linkedOpportunityGetDTO.getQueryTime();
            Integer queryType = linkedOpportunityGetDTO.getQueryType();
            Set<String> permSet = loginUser.getPermSet();
            if(!permSet.contains(ProPermissionAliasEnum.OPPORTUNITY_VIEW.getAlias())){
                throw new XbbException(OpportunityErrorCodeEnum.API_ERROR_202004);
            }

            List<PaasFormEntityExt> enableFormList = paasFormModel.getEnableFormList(corpid, XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
            Map<Long,PaasFormEntityExt> enableFormIdMap= new HashMap<>();
            enableFormList.forEach(item->{
                enableFormIdMap.put(item.getId(),item);
            });
            Set<Long> enableFormIdSet = new HashSet<>();
            enableFormList.forEach(item->{
                enableFormIdSet.add(item.getId());
            });

            List<PaasFormExplainEntity> paasFormExplainEntityList = paasFormExplainModel.getByFormIdIn(enableFormIdSet, corpid);
            Map<Long,PaasFormExplainEntity> paasFormExplainEntityFormIdMap= new HashMap<>();
            paasFormExplainEntityList.forEach(item->{
                paasFormExplainEntityFormIdMap.put(item.getFormId(),item);
            });

            Map<String,Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(StringConstant.CORPID,corpid);
            params.put("competitorId",dataId);
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            List<CompetitorAnalysisEntity> competitorAnalysisModelEntitys = competitorAnalysisModel.findEntitys(params);
            Set<Long> opportunityIdSet = new HashSet<>();
            competitorAnalysisModelEntitys.forEach(item->{
                opportunityIdSet.add(item.getOppotunityId());
            });

            params.clear();
            params.put(StringConstant.CORPID,corpid);
//        params.put("idIn",stageIdSet);
            params.put("typeIn", Arrays.asList(StageTypeEnum.SUCCESS_STAGE.getType(),StageTypeEnum.FAIL_STAGE.getType()));
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            List<SaleStageEntity> saleStageEntityList = saleStageModel.findEntitys(params);
            Set<Long> successSaleStageIdSet = new HashSet<>();
            Set<Long> failSaleStageIdSet = new HashSet<>();
            saleStageEntityList.forEach(item->{
                Integer type = item.getType();
                if(Objects.equals(type,StageTypeEnum.SUCCESS_STAGE.getType())){
                    successSaleStageIdSet.add(item.getId());
                }else if(Objects.equals(type,StageTypeEnum.FAIL_STAGE.getType())){
                    failSaleStageIdSet.add(item.getId());
                }
            });
            QueryLinkedOpportunityPojo queryLinkedOpportunityPojo
                    = new QueryLinkedOpportunityPojo(queryTime,queryType,successSaleStageIdSet,failSaleStageIdSet,dataId);
            // 查询机会集合
            List<PaasFormDataEntityExt> opportunityEntityExtList =
                    getOpportunity(corpid,userId, opportunityIdSet,enableFormIdSet,loginUser,page,pageSize,queryLinkedOpportunityPojo );
            // 获取预期金额汇总
            double amount = getOpportunityEstimateAmount(corpid,userId, opportunityIdSet,enableFormIdSet,loginUser,queryLinkedOpportunityPojo);

            for(int i =0; i<opportunityEntityExtList.size(); i++) {
                LinkedOpportunityItemEntity linkedOpportunityItemEntity = new LinkedOpportunityItemEntity();
                PaasFormDataEntityExt item = opportunityEntityExtList.get(i);
                item.setBusinessType(XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
                item.setSaasMark(SaasMarkEnum.SAAS.getCode());
                Long id = item.getId();
                JSONObject data = item.getData();
                Long stageId = data.getLong(SalesOpportunityEnum.STAGE_ID.getAttr());
                // 啥都没有
                linkedOpportunityItemEntity.setType(0);
                if (successSaleStageIdSet.contains(stageId)) {
                    // 我们赢
                    linkedOpportunityItemEntity.setType(1);
                }
                Long competitorId = data.getLong(SalesOpportunityEnum.WIN_COMPETITOR.getAttr());
                if (competitorId == dataId /*&& failSaleStageIdSet.contains(stageId)*/) {
                    // 对手赢
                    linkedOpportunityItemEntity.setType(2);
                }
                if (successSaleStageIdSet.contains(stageId) && competitorId == dataId ) {
                    // 我们赢和对手赢
                    linkedOpportunityItemEntity.setType(3);
                }

                PaasFormEntityExt paasFormEntityExt = enableFormIdMap.get(item.getFormId());
                PaasFormExplainEntity paasFormExplainEntity = paasFormExplainEntityFormIdMap.get(item.getFormId());
                String  explains = paasFormExplainEntity.getExplains();
                Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explains, null);
                // 解析摘要
                FormDataGetDTO formDataGetDTO = new FormDataGetDTO();
                BeanUtil.copyProperties(linkedOpportunityGetDTO,formDataGetDTO);
                List<SummaryDataPoJo> summaryDataPoJos = formatDataSummary(corpid, item.getBusinessType(), explainMap,
                        item.getDataId(),formDataGetDTO,
                        item, paasFormExplainEntity, paasFormEntityExt,linkedOpportunityGetDTO);

                String name = FastJsonHelper.getStringOrDefaultFromFormData(data, SalesOpportunityEnum.NAME.getAttr(), "");
                name = item.getSerialNo()+"（" + name + "）";
                linkedOpportunityItemEntity.setBusinessType(item.getBusinessType());
                linkedOpportunityItemEntity.setDataId(item.getDataId());
//            linkedOpportunityItemEntity.setEntity(item);
                linkedOpportunityItemEntity.setFormId(item.getFormId());
                linkedOpportunityItemEntity.setSaasMark(item.getSaasMark());
                linkedOpportunityItemEntity.setSummaryList(summaryDataPoJos);
                linkedOpportunityItemEntity.setName(name);
                linkedOpportunityItemEntityArrayList.add(linkedOpportunityItemEntity);
            }

            // 查询总条数 用来分页
            long count = getOpportunityCount(corpid,userId, opportunityIdSet,enableFormIdSet,loginUser,queryLinkedOpportunityPojo);
            PageHelper pageHelper = new PageHelper(page, pageSize);
            pageHelper.setRowsCount((int) count);
            linkedOpportunityListVO.setPageHelper(pageHelper);
            linkedOpportunityListVO.setAmount(amount);
        }catch (Exception e){
            log.error("CompetitorServiceImpl.linkedOpportunityList exception:" + e);
            throw e;
        }
        return linkedOpportunityListVO;
    }

    @Override
    public FormDataAddDTO formatExcelValue(ImportFormDataDTO importFormDataDTO, List<CellTitlePojo> titlePojoList, RowGroupPojo rowGroupPojo, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
        BeanUtil.copyProperties(importFormDataDTO,formDataAddDTO);
        JSONObject dataJson = new JSONObject();
        List<List<CellValuePojo>> rowValueList = rowGroupPojo.getRowValueList();
        List<CellValuePojo> cellValueList = rowValueList.get(0);

        String corpid = importFormDataDTO.getCorpid();

        for (FieldAttrEntityForImport fieldAttr : fieldAttrList) {
            String attr = fieldAttr.getAttr();
            Integer fieldType = fieldAttr.getFieldType();
            String attrName = fieldAttr.getAttrName();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);
            if (Objects.equals(fieldType,FieldTypeEnum.SUB_FORM.getType())){
                importHelper.formatSubFormValue4Import(rowValueList, titlePojoList, importFormDataDTO,fieldAttr, dataJson);
            }else {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    continue;
                }
                if (ImportHelper.commonHandleFieldType.contains(fieldType)) {
                    importHelper.formatCommonField(dataJson, fieldAttr, cellValue);
                } else if (Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType())) {
                    formDataAddDTO.setSerialNo(cellValue.toString());
                }else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA.getType())){
                    importHelper.formatLinkData(cellValue, fieldAttr, dataJson);
                }
                else {
                    dataJson.put(attr, cellValue);
                }
            }
        }

        formDataAddDTO.setDataList(dataJson);
        return formDataAddDTO;
    }

    @Override
    public void updateBatchLabelAttr(AddLabelDTO addLabelDTO, List<PaasFormDataEntityExt> addBatchList, Boolean addOrDelete) throws XbbException {
        CompetitorUpdateBatchDTO competitorUpdateBatchDTO = new CompetitorUpdateBatchDTO();
        BeanUtil.copyProperties(addLabelDTO,competitorUpdateBatchDTO);
        List<CompetitorUpdateDTO> competitorUpdateDTOList = addBatchList.stream().map(item -> {
            CompetitorUpdateDTO competitorUpdateDTO = new CompetitorUpdateDTO();
            competitorUpdateDTO.setData(item.getData());
            competitorUpdateDTO.setId(item.getId());
            return competitorUpdateDTO;
        }).collect(Collectors.toList());

        competitorUpdateBatchDTO.setCompetitorUpdateDTOList(competitorUpdateDTOList);

        updateBatch(competitorUpdateBatchDTO);

    }

    public List<SummaryDataPoJo> formatDataSummary(String corpid, Integer businessType,
         Map<String, FieldAttrEntity> explainMap, Long dataId,FormDataGetDTO formDataGetDTO,
         PaasFormDataEntityExt paasFormDataEntityExt, PaasFormExplainEntity paasFormExplainEntity,
                                                   PaasFormEntityExt paasFormEntityExt,LinkedOpportunityListDTO linkedOpportunityGetDTO) throws XbbException {
        // 去获取表单模板中的信息
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        BeanUtil.copyProperties(linkedOpportunityGetDTO, handlerExplainDTO, false);
        handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
        UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
        BeanUtil.copyProperties(linkedOpportunityGetDTO, userAndDepartmentGetDTO);
        userAndDepartmentGetDTO.setExplainList(explainList);
        Map<String, UserEntity> userMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        handlerExplainDTO.setExplainList(explainList);
        // 获取协同人和负责人
        JSONObject ownerAndCoUser = paasFormHelp.getOwnerIdAndCoUserId(handlerExplainDTO, SaasMarkEnum.SAAS.getCode(), businessType, businessType, paasFormDataEntityExt, userMap);
        handlerExplainDTO.setPaasFormEntityExt(paasFormEntityExt);
        handlerExplainDTO.setFormData(paasFormDataEntityExt.getData());
        // 获取表单解释
        HandlerExplainVO handlerExplainVO = formDataDetailFormExplainHandleName.handleExplain(handlerExplainDTO);
        explainMap = ExplainUtil.getExplainMap(JSONObject.toJSONString(handlerExplainVO.getHeadList()), null);
        List<Long> dataIdIn = new ArrayList<>();
        dataIdIn.add(dataId);
        //协同团队
        Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (CollectionsUtil.isNotEmpty(dataIdIn)){
            userTeamHelp.setUserIdMap(dataIdIn, corpid, businessType, false, mainUserMap, coUserMap);
        }
        BeanUtil.copyProperties(formDataGetDTO, handlerExplainDTO, false);
        handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
        // ---- 获取用户和部门容器start

        Map<String, DepartmentEntity> departmentMap = commonHelp.getDepMap(userAndDepartmentGetDTO);
          JSONObject data = paasFormDataEntityExt.getData();
        data.put(FieldTypeEnum.ADDTIME.getAlias(), paasFormDataEntityExt.getAddTime());
        data.put(FieldTypeEnum.UPDATETIME.getAlias(), paasFormDataEntityExt.getUpdateTime());
        data.put(FieldTypeEnum.SERIALNO.getAlias(), paasFormDataEntityExt.getSerialNo());
        data.put(FieldTypeEnum.CREATORID.getAlias(), paasFormDataEntityExt.getCreatorId());
        data.put(FieldTypeEnum.DEPARTMENTID.getAlias(), paasFormDataEntityExt.getDepartmentId());
        data.putAll(ownerAndCoUser);
        ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
        BeanUtil.copyProperties(formDataGetDTO, parseSingleRowDataDTO);
        parseSingleRowDataDTO.setDataJsonObject(data);
        parseSingleRowDataDTO.setExplainMap(explainMap);
        parseSingleRowDataDTO.setUserMap(userMap);
        parseSingleRowDataDTO.setDepartmentMap(departmentMap);
        // 解析数据
        ParseSingleRowDataVO parseSingleRowDataVO = formDataGetAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
        if ( Objects.isNull(parseSingleRowDataVO) ) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PARSE_SINGLE_ROW_DATA_FAILED);
        }
        data = parseSingleRowDataVO.getResult();
        // 解析摘要
        List<SummaryDataPoJo> summaryList = ExplainUtil.getSpecialSummaryList(paasFormEntityExt.getSummaryList(), data, explainMap, paasFormDataEntityExt);

        for(SummaryDataPoJo item: summaryList){
            String attr = item.getAttr();
            if (Objects.equals(attr, SalesOpportunityEnum.SALE_STAGE.getAttr())){
                JSONObject tempData = paasFormDataEntityExt.getData();
                Long stageId = tempData.getLong(SalesOpportunityEnum.STAGE_ID.getAttr());
                Long stageProcessId = tempData.getLong(SalesOpportunityEnum.STAGE_PROCESS_ID.getAttr());
                if(stageId!=null && stageProcessId!=null){
                    SaleStageEntity saleStageEntity = saleStageModel.getByKey(stageId, corpid);
                    String name = saleStageEntity.getName();
                    item.setValue(Arrays.asList(name));
                }
                break;
            }
        }

        return summaryList;
    }

    /**
     * 记录批量删除日志
     *
     * @param deleteList
     * @param competitorDeleteBatchDTO
     */
    private void recordBatchDeleteLog(List<CompetitorEntity> deleteList, CompetitorDeleteBatchDTO competitorDeleteBatchDTO) throws XbbException {

        String loginUserName = competitorDeleteBatchDTO.getLoginUserName();
        String corpid = competitorDeleteBatchDTO.getCorpid();
        String userId = competitorDeleteBatchDTO.getUserId();

        String nameListStr = deleteList.stream().map(competitorEntity -> FastJsonHelper.getStringOrDefault(competitorEntity.getData(),CompetitorEnum.NAME.getAttr(),"")).collect(Collectors.joining(","));

        if (deleteList.size() > 1) {
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_DELETE_FORM_DETAIL), loginUserName, XbbRefTypeEnum.COMPETITOR.getName(), deleteList.size());
            InfoArrPojo infoArrPojo = new InfoArrPojo();
            infoArrPojo.setTitle(CompetitorEnum.NAME.getAttr());
            infoArrPojo.setContent(nameListStr);
            mongoLogHelp.buildLog4InfoArr(Collections.singletonList(infoArrPojo),corpid,userId, loginUserName, OperateModuleTypeEnum.COMPETITOR, OperateTypeEnum.DELETE,
                    "", "", memo, competitorDeleteBatchDTO.getHttpHeader());
        }else if (deleteList.size() == 1){
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), loginUserName, XbbRefTypeEnum.COMPETITOR.getName(), nameListStr);
            mongoLogHelp.buildLog(corpid,userId,loginUserName,OperateModuleTypeEnum.COMPETITOR, OperateTypeEnum.DELETE, deleteList.get(0).getId().toString(),
                    nameListStr, memo, competitorDeleteBatchDTO.getHttpHeader());
        }
    }

    /**
     * 竞争对手详情tab查询关联机会 封装查询条件
     * date: 2022/8/25 9:36 上午
     * @author yingjf
     * @param boolQueryBuilder:
     * @param queryLinkedOpportunityPojo:
     */
    private void setQueryCondition(BoolQueryBuilder boolQueryBuilder,QueryLinkedOpportunityPojo queryLinkedOpportunityPojo){
        if(queryLinkedOpportunityPojo==null){
            return;
        }
        Integer queryType = queryLinkedOpportunityPojo.getQueryType();
        Set<Long> successSaleStageIdSet = queryLinkedOpportunityPojo.getSuccessSaleStageIdSet();
        Set<Long> failSaleStageIdSet = queryLinkedOpportunityPojo.getFailSaleStageIdSet();
        JSONArray queryTime = queryLinkedOpportunityPojo.getQueryTime();
        Long dataId = queryLinkedOpportunityPojo.getDataId();
        // 查询类型  null查全部，1 查我们赢 2对手赢
        if(queryType==null || queryType==0){

        }else if(queryType==1){
            boolQueryBuilder.must(termsQuery(SalesOpportunityEnum.getEsAttr4Keyword(SalesOpportunityEnum.STAGE_ID), successSaleStageIdSet));
        }else if(queryType==2){
            //boolQueryBuilder.must(termsQuery(SalesOpportunityEnum.getEsAttr4Keyword(SalesOpportunityEnum.STAGE_ID), failSaleStageIdSet));
            boolQueryBuilder.must(termQuery(SalesOpportunityEnum.getEsAttr4Keyword(SalesOpportunityEnum.WIN_COMPETITOR), dataId));
        }
        // 封装查询时间
        if(CollectionsUtil.isNotEmpty(queryTime)){
            List<Object> timeList = BasicHelper.timeStrToValueList(queryTime);
            boolQueryBuilder.filter(rangeQuery(SalesOpportunityEnum.ADD_TIME.getAttr()).gte(timeList.get(0)).lte(timeList.get(1)));
        }
    }

    /**
     * 查询机会数量
     * date: 2022/8/24 3:01 下午
     * @author yingjf
     * @param corpid:
     * @param userId:
     * @param opportunityIdSet:
     * @param enableFormIdSet:
     * @param userVO:
     */
    private Long getOpportunityCount(String corpid,String userId, Set<Long> opportunityIdSet,
                                                      Set<Long> enableFormIdSet,UserVO userVO,QueryLinkedOpportunityPojo queryLinkedOpportunityPojo)throws XbbException{
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        //解析查询条件
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        // 权限
        setDataPermission(userVO,boolQueryBuilder,IndexTypeEnum.IDX_SAAS_OPPORTUNITY_TEAM);
        // 设置查询条件
        setQueryCondition(boolQueryBuilder,queryLinkedOpportunityPojo);

        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_OPPORTUNITY.getType()));
        boolQueryBuilder.filter(termsQuery("formId",enableFormIdSet));
        boolQueryBuilder.filter(termsQuery(StringConstant.DATA_ID, opportunityIdSet));
        boolQueryBuilder.filter(termsQuery("flowStatus", FlowStatusEnum.getStatisticType()));
        sourceBuilder.query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_OPPORTUNITY.getIndex());
        searchRequest.source(sourceBuilder);
        Long count = xbbElasticsearchRestTemplate.count(searchRequest, PaasFormDataEntityExt.class);
        return count;
    }

    /**
     * 获取预期金额汇总
     * date: 2022/9/15 2:29 下午
     * @author yingjf
     * @param corpid:
     * @param userId:
     * @param opportunityIdSet:
     * @param enableFormIdSet:
     * @param userVO:
     * @param queryLinkedOpportunityPojo:
     */
    private double getOpportunityEstimateAmount(String corpid,String userId, Set<Long> opportunityIdSet,
                                     Set<Long> enableFormIdSet,UserVO userVO,QueryLinkedOpportunityPojo queryLinkedOpportunityPojo)throws XbbException{
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        //解析查询条件
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        // 权限
        setDataPermission(userVO,boolQueryBuilder,IndexTypeEnum.IDX_SAAS_OPPORTUNITY_TEAM);
        // 设置查询条件
        setQueryCondition(boolQueryBuilder,queryLinkedOpportunityPojo);

        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_OPPORTUNITY.getType()));
        boolQueryBuilder.filter(termsQuery("formId",enableFormIdSet));
        boolQueryBuilder.filter(termsQuery(StringConstant.DATA_ID, opportunityIdSet));
        boolQueryBuilder.filter(termsQuery("flowStatus", FlowStatusEnum.getStatisticType()));

        String estimateAmountAttr = SalesOpportunityEnum.getEsAttr4Keyword(SalesOpportunityEnum.ESTIMATE_AMOUNT);
        List<String> sumFieldList = Arrays.asList(estimateAmountAttr);
        JSONObject result = esHelper.sumMuchField4Some(IndexTypeEnum.IDX_SAAS_OPPORTUNITY, boolQueryBuilder, sumFieldList);

        return result.getDoubleValue(estimateAmountAttr);
    }




    /**
     * 查询机会
     * date: 2022/8/23 9:36 上午
     * @author yingjf
     * @param corpid: 公司id
     * @param userId:  用户id
     * @param opportunityIdSet: 机会id集合
     * @param enableFormIdSet: 开启的表单的集合
     */
    private List<PaasFormDataEntityExt> getOpportunity(String corpid, String userId, Set<Long> opportunityIdSet,
                                                       Set<Long> enableFormIdSet, UserVO userVO, Integer page, Integer pageSize, QueryLinkedOpportunityPojo queryLinkedOpportunityPojo)throws XbbException{
        List<OpportunityEntityExt> res = new ArrayList<>();
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        //解析查询条件
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        // 权限
        setDataPermission(userVO,boolQueryBuilder,IndexTypeEnum.IDX_SAAS_OPPORTUNITY_TEAM);
        // 设置查询条件
        setQueryCondition(boolQueryBuilder,queryLinkedOpportunityPojo);

        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_OPPORTUNITY.getType()));
        boolQueryBuilder.filter(termsQuery("formId",enableFormIdSet));
        boolQueryBuilder.filter(termsQuery(StringConstant.DATA_ID, opportunityIdSet));
        boolQueryBuilder.filter(termsQuery("flowStatus", FlowStatusEnum.getStatisticType()));
        sourceBuilder.query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_OPPORTUNITY.getIndex());
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, page, pageSize);
        searchRequest.source(sourceBuilder);
        XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest,searchRequest, PaasFormDataEntityExt.class);
        return esEntities.getContent();
    }

    private List<PaasFormDataEntityExt> getOpportunity(String corpid,String userId, Set<Long> opportunityIdSet,
                                                      Set<Long> enableFormIdSet,UserVO userVO)throws XbbException{
       return getOpportunity( corpid, userId,opportunityIdSet,enableFormIdSet,userVO,0,10000,null);
    }

    private void setDataPermission(UserVO userVO, BoolQueryBuilder boolQueryBuilder, IndexTypeEnum indexTypeEnum) {
        if(userVO==null){
            return;
        }
        //判断员工是否拥有“机会”模块的最大数据权限
        Boolean haveAllDataPermission = false;
        Map<String, Integer> dataPermissionDetail = userVO.getDataPermissionDetail();
        if (Objects.nonNull(dataPermissionDetail) && dataPermissionDetail.size() > 0) {
            Integer dataPermission = dataPermissionDetail.get(SaasMarkEnum.SAAS.getCode() + "_" + XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
            haveAllDataPermission = DataPermissionEnum.ALL.getCode().equals(dataPermission);
        }
        //如果是最大数据权限，则不需要添加 任何的userId 限制
        if (haveAllDataPermission) {
            return;
        }
        //不是最大权限，则需要添加userId的权限限制
        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(userVO, userEntity);
        Integer dataPermission = userModel.getDataPermission(userEntity);
        List<String> userIdIn = userModel.getSubIdListByDataPermission(dataPermission, userVO.getUserId(), userVO.getCorpid(), BasicConstant.ZERO, false);
        HasChildQueryBuilder hasChildQueryBuilder = esHelper.teamQueryBuilder(indexTypeEnum, userVO.getCorpid(), null, userIdIn);
        boolQueryBuilder.must(hasChildQueryBuilder);
    }



    /**
     * 封装全景分析结果 空结果
     * date: 2022/8/23 10:12 上午
     * @author yingjf
     * @param :
     */
    public List<List<CompetitorPanoramaDataVO>> packageEmptyPanoramaList(String saleOpportunityMenuName){
        return packagePanoramaList(false,saleOpportunityMenuName,0L,0.0,0L,0.0,0L,0.0);
    }
    /**
     * 封装全景分析结果
     * date: 2022/8/23 10:00 上午
     * @author yingjf
     * @param :
     */
    public List<List<CompetitorPanoramaDataVO>> packagePanoramaList(boolean canSee,String saleOpportunityMenuName,Long opportunityCount,Double opportunityMoney,
         Long winOpportunityCount,Double winOpportunityMoney,Long loseOpportunityCount,Double loseOpportunityMoney){
        List<List<CompetitorPanoramaDataVO>> res = new ArrayList<>();
        List<CompetitorPanoramaDataVO> line1 = new ArrayList<>();
        List<CompetitorPanoramaDataVO> line2 = new ArrayList<>();
        List<CompetitorPanoramaDataVO> line3 = new ArrayList<>();
        res.add(line1);
        res.add(line2);
        res.add(line3);
        CompetitorPanoramaDataVO opportunityCountItem = new CompetitorPanoramaDataVO(canSee,CompetitorPanoramaEnum.OPPORTUNITY_COUNT,saleOpportunityMenuName,opportunityCount.toString());
        CompetitorPanoramaDataVO opportunityMoneyItem = new CompetitorPanoramaDataVO(canSee,CompetitorPanoramaEnum.OPPORTUNITY_MONEY,saleOpportunityMenuName,opportunityMoney.toString());
        line1.add(opportunityCountItem);
        line1.add(opportunityMoneyItem);
        CompetitorPanoramaDataVO winOpportunityCountItem = new CompetitorPanoramaDataVO(canSee,CompetitorPanoramaEnum.WIN_OPPORTUNITY_COUNT,saleOpportunityMenuName,winOpportunityCount.toString());
        CompetitorPanoramaDataVO winOpportunityMoneyItem = new CompetitorPanoramaDataVO(canSee,CompetitorPanoramaEnum.WIN_OPPORTUNITY_MONEY,saleOpportunityMenuName,winOpportunityMoney.toString());
        line2.add(winOpportunityCountItem);
        line2.add(winOpportunityMoneyItem);
        CompetitorPanoramaDataVO loseOpportunityCountItem = new CompetitorPanoramaDataVO(canSee,CompetitorPanoramaEnum.LOSE_OPPORTUNITY_COUNT,saleOpportunityMenuName,loseOpportunityCount.toString());
        CompetitorPanoramaDataVO loseOpportunityMoneyItem = new CompetitorPanoramaDataVO(canSee,CompetitorPanoramaEnum.LOSE_OPPORTUNITY_MONEY,saleOpportunityMenuName,loseOpportunityMoney.toString());
        line3.add(loseOpportunityCountItem);
        line3.add(loseOpportunityMoneyItem);
        return res;
    }

    /**
     * 判断详情页是否开启销售机会，如果关闭，则全景图不再展示任何内容（竞争对手全景图目前只有销售机会相关内容）
     * @param competitorPanoramaGetDTO
     * @return
     */
    private boolean isOpenSaleOpportunityTab(CompetitorPanoramaGetDTO competitorPanoramaGetDTO){
        String corpid = competitorPanoramaGetDTO.getCorpid();
        String userId = competitorPanoramaGetDTO.getUserId();
        Long dataId = competitorPanoramaGetDTO.getDataId();
        CompetitorEntity competitor = competitorModel.getByKey(dataId, corpid);
        Long formId = competitor.getFormId();
        Map<String, Object> getParam = new HashMap<>();
        getParam.put("corpid",corpid);
        getParam.put("userId",userId);
        getParam.put("formId",formId);
        List<DetailTabConfigEntity> detailTabConfigEntityList = detailTabConfigModel.findEntitys(getParam);
        if (CollectionUtils.isEmpty(detailTabConfigEntityList)) {
            return true;
        }
        DetailTabConfigEntity detailTabConfigEntity = detailTabConfigEntityList.get(0);
        JSONArray configList = JSONArray.parseArray(detailTabConfigEntity.getTabConfig());
        for (Object config : configList) {
            JSONObject itemConfig = JSONObject.parseObject(JSONObject.toJSONString(config));
            if (StringUtils.equals(itemConfig.get("key").toString(), DetailTabEnum.COMPETITOR_LINKED_OPPORTUNITY.getKey())){
                return StringUtils.equals(itemConfig.get("enable").toString(),"1");
            }
        }
        return true;
    }
}
